// Copyright (c) XiGuan 2023
// Author： xiguan
// Email: xiguan.teng@qq.com
// Create on 2023/10/28
// TODO:
//

#ifndef WEBSERVER_LOGD_LOG_H
#define WEBSERVER_LOGD_LOG_H

#include <BlockDeque.h>
#include <Buffer.h>

#include <mutex>
#include <thread>

class Log {
 private:
  static const int LOG_PATH_LEN = 256;
  static const int LOG_NAME_LEN = 256;
  static const int MAX_LINES = 65536;

  const char *path_;
  const char *suffix_;

  int line_count_;
  int today_;

  bool is_open_;

  Buffer buffer_;
  int level_;
  bool is_async_;  // 异步

  FILE *fp_;
  std::unique_ptr<BlockDeque<std::string>> deque_;
  std::unique_ptr<std::thread> write_thread_;
  std::mutex mtx_;

 public:
  void init(int _level, const char *_path = "./log",
            const char *_suffix = ".log", int _max_queue_capacity = 1024);
  static Log *Instance();
  static void flush_log_thread();
  void flush();

  int getLevel();
  void setLevel(int _level);
  bool isOpen() const;

  void write(int _level, const char *format, ...);

 private:
  Log();
  virtual ~Log();
  void async_write_();
  void append_log_level_title(int _level);
};

#define LOG_BASE(level, format, ...)                 \
  do {                                               \
    Log *log = Log::Instance();                      \
    if (log->isOpen() && log->getLevel() <= level) { \
      log->write(level, format, ##__VA_ARGS__);      \
      log->flush();                                  \
    }                                                \
  } while (0);

#define LOG_DEBUG(format, ...)          \
  do {                                  \
    LOG_BASE(0, format, ##__VA_ARGS__); \
  } while (0);

#define LOG_INFO(format, ...)           \
  do {                                  \
    LOG_BASE(1, format, ##__VA_ARGS__); \
  } while (0);

#define LOG_WARN(format, ...)           \
  do {                                  \
    LOG_BASE(2, format, ##__VA_ARGS__); \
  } while (0);

#define LOG_ERROR(format, ...)          \
  do {                                  \
    LOG_BASE(3, format, ##__VA_ARGS__); \
  } while (0);

#endif  // WEBSERVER_LOGD_LOG_H
